#include "g_local2.h"

static Party *_head = NULL;

const Party *GetPartyHead()
{
	return _head;
}

const Party *FindParty(const char *uid)
{
	for (Party *party = _head; party != NULL; party = party->Next)
		if (Q_stricmp(party->Name, uid) == 0)
			return party;

	return NULL;
}

Party *CreateParty(const char *uid)
{
	gi.dprintf("(PARTY) Creating party %s.\n", uid);

	Party *newParty = new Party;
	memset(newParty, 0, sizeof(Party));

	newParty->Name = new char[strlen(uid) + 1];
	Q_strncpyz(newParty->Name, uid, strlen(uid) + 1);

	if (_head == NULL)
		_head = newParty;
	else
	{
		for (Party *party = _head; ; party = party->Next)
		{
			if (party->Next == NULL)
			{
				party->Next = newParty;
				break;
			}
		}
	}

	return newParty;
}

static Party *GetPrev(const Party *party)
{
	for (Party *par = _head; par != NULL; par = par->Next)
		if (par->Next == party)
			return par;

	return NULL;
}

void DeleteParty(Party *party)
{
	gi.dprintf("(PARTY) Deleting party %s.\n", party->Name);

	for (PlayerLinkedListNode *node = party->Characters; node != NULL; node = node->Next)
	{
		RemovePlayerFromParty(node->Data);
		CheckPartilessPlayer(node->Data);
	}

	if (_head == party)
		_head = party->Next;
	else
		GetPrev(party)->Next = party->Next;

	delete party->Name;
	delete party;
}

void AddPlayerToParty(CharacterData *player, const Party *party)
{
	gi.dprintf("(PARTY) Adding %s to party %s.\n", player->Player->client->pers.netname, party->Name);

	if (player->Party != NULL)
	{
		gi.dprintf("(PARTY) Player already in a party.\n");
		RemovePlayerFromParty(player);
	}

	PlayerLinkedListNode *node;

	for (node = party->Characters; node != NULL && node->Next != NULL; node = node->Next) ;

	PlayerLinkedListNode **whereNode;
	Party *unConst = const_cast<Party*>(party);

	if (node == NULL)
		whereNode = &unConst->Characters;
	else
		whereNode = &node->Next;

	*whereNode = new PlayerLinkedListNode;
	(*whereNode)->Data = player;
	(*whereNode)->Next = NULL;

	player->Party = unConst;
	unConst->PlayerCount++;
}

void RemovePlayerFromParty(CharacterData *player)
{
	PlayerLinkedListNode *node, *prevNode = NULL;
	Party *party = player->Party;

	gi.dprintf("(PARTY) Removing %s from party %s.\n", player->Player->client->pers.netname, party->Name);

	for (node = party->Characters; node != NULL; node = node->Next)
	{
		if (node->Next != NULL && node->Next->Data == player)
			prevNode = node;
		else if (node->Data == player)
			break;
	}

	if (prevNode != NULL)
		prevNode->Next = node->Next;
	else
		party->Characters = node->Next;

	delete node;
	party->PlayerCount--;

	if (party->PlayerCount == 0)
		DeleteParty(party);

	player->Party = NULL;
}

void CheckPartilessPlayer(CharacterData *player)
{
	if (player->Party != NULL)
	{
		gi.dprintf("(PARTY) Player %s is not partiless (%s).\n", player->Player->client->pers.netname, player->Party->Name);
		return;
	}

	gi.dprintf("(PARTY) Player %s is partiless.\n", player->Player->client->pers.netname);
	Party *newParty = CreateParty(va("%s's Party", player->Player->client->pers.netname));
	AddPlayerToParty(player, newParty);
}